package vip.wangwenhao.util;

import org.apache.commons.collections.CollectionUtils;
import vip.wangwenhao.mojo.GeneralMojo;
import vip.wangwenhao.vo.ColumnInfo;
import vip.wangwenhao.vo.IndexInfo;

import java.io.File;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wwh
 * @date 2019年12月04日 18:12
 */

public class GenMapperXmlUtil {

    public static List<String> tablePrefixes;
    public static List<String> columnPrefixes;
    public static String mapperXmlPath;
    public static String mapperPackage;
    public static String beanPackage;

    public static void init(GeneralMojo generalMojo) {
        tablePrefixes = generalMojo.getTablePrefixes();
        columnPrefixes = generalMojo.getColumnPrefixes();
        mapperXmlPath = generalMojo.getMapperXmlPath();
        mapperPackage = generalMojo.getMapperPackage();
        beanPackage = generalMojo.getBeanPackage();
    }

    public static void createMapperXml(String tableName) {
        String beanName = StringUtil.initCap(tableName, true, tablePrefixes);

        String resultMap = "";
        String insertElement = "";
        String insertElementParam = "";
        String updateElement = "";
        String updateElementParam = "        where ";
        String filterElement = "";


        List<ColumnInfo> tablePrimary = DatabaseUtil.getTablePrimary(tableName);
        List<IndexInfo> indexInfos = DatabaseUtil.getIndex(tableName);
        List<ColumnInfo> columnInfos = DatabaseUtil.getColumnInfos(tableName);
        if (CollectionUtils.isNotEmpty(columnInfos)) {
            for (ColumnInfo columnInfo : columnInfos) {

                if (columnInfo.getColumnType().getJavaType().equals("String")) {
                    insertElement += "            <if test=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "!=null and " + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + " !=''\">" + columnInfo.getColumnName() + ",</if>\n";
                    insertElementParam += "            <if test=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "!=null and " + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + " !=''\">#{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + ",jdbcType=" + columnInfo.getColumnType() + "},</if>\n";
                    updateElement += "            <if test=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "!=null and " + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + " !=''\">" + columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + ",jdbcType=" + columnInfo.getColumnType() + "},</if>\n";
                    filterElement += "            <if test=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + " != null and " + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + " != ''\">\n" +
                            "                and " + columnInfo.getColumnName() + " like #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "}\n" +
                            "            </if>\n";

                } else {
                    insertElement += "            <if test=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "!=null \">" + columnInfo.getColumnName() + ",</if>\n";
                    insertElementParam += "            <if test=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "!=null \">#{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + ",jdbcType=" + columnInfo.getColumnType() + "},</if>\n";
                    updateElement += "            <if test=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "!=null\">" + columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + ",jdbcType=" + columnInfo.getColumnType() + "},</if>\n";
                    filterElement += "            <if test=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + " != null \">\n" +
                            "                and " + columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "}\n" +
                            "            </if>\n";
                }

                if (tablePrimary.stream().anyMatch(columnInfo1 -> columnInfo1.getColumnName().equals(columnInfo.getColumnName()))) {
                    resultMap += "        <id column=\"" + columnInfo.getColumnName() + "\" jdbcType=\"" + columnInfo.getColumnType() + "\" property=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "\"/>\n";
                    updateElementParam += columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + ",jdbcType=" + columnInfo.getColumnType() + "}";
                } else {
                    resultMap += "        <result column=\"" + columnInfo.getColumnName() + "\" jdbcType=\"" + columnInfo.getColumnType() + "\" property=\"" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "\"/>\n";
                }
                updateElementParam += "\n";

            }
        }

        String columnList = String.join(",", DatabaseUtil.getColumnNames(tableName));


        String insert = "   <insert id=\"insert\" parameterType=\"" + beanPackage + "." + beanName + "\" >\n" +
                "        INSERT INTO " + tableName + "\n" +
                "        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n" +
                insertElement +
                "        </trim>\n" +
                "        VALUES\n" +
                "        <trim prefix=\"(\" suffix=\")\" suffixOverrides=\",\">\n" +
                insertElementParam +
                "        </trim>\n" +
                "    </insert>";


        String update = "   <update id=\"update\" parameterType=\"" + beanPackage + "." + beanName + "\">\n" +
                "        UPDATE " + tableName + "\n" +
                "        <set>\n" +
                updateElement +
                "        </set>\n" +
                updateElementParam +
                "    </update>";

        String delete = "";
        String selectByPrimaryKey = "";
        StringBuffer selectByIndex = new StringBuffer();

        String query = "    <select id=\"query\" parameterType=\"" + beanPackage + "." + beanName + "\"\n" +
                "            resultMap=\"BaseResultMap\">\n" +
                "        select\n" +
                "        <include refid=\"Base_Column_List\"/>\n" +
                "        from " + tableName + "\n" +
                "        <include refid=\"Filter_List\"/>\n" +
                "    </select>";

        String filterList = "   <sql id=\"Filter_List\">\n" +
                "        <where>\n" +
                filterElement +
                "        </where>\n" +
                "    </sql>";
        if (tablePrimary.size() > 0) {
            selectByPrimaryKey += "   <select id=\"selectByPrimaryKey\" resultMap=\"BaseResultMap\">\n" +
                    "        select\n" +
                    "        <include refid=\"Base_Column_List\"/>\n" +
                    "        from " + tableName + "\n" +
                    "        where ";
            String condition = "";
            if (tablePrimary.size() > 1) {
                for (ColumnInfo columnInfo : tablePrimary) {
                    condition += columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "} and";
                }
                condition = condition.substring(0, condition.length() - 4);
                delete += "   <delete id=\"delete\" >\n" +
                        "        delete from " + tableName + " where " + condition + "\n" +
                        "    </delete>";
                selectByPrimaryKey += condition + "\n";
            } else {
                ColumnInfo columnInfo = tablePrimary.get(0);
                String javaType = columnInfo.getColumnType().getJavaType();
                delete += "   <delete id=\"delete\" parameterType=\"" + javaType + "\">\n" +
                        "        delete from " + tableName + " where " + columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "}\n" +
                        "    </delete>";

                selectByPrimaryKey += columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "}\n";
            }
            selectByPrimaryKey += "    </select>";

        }


        if (CollectionUtils.isNotEmpty(indexInfos)){
            indexInfos.forEach(indexInfo->{
                if (!"PRIMARY".equals(indexInfo.getIndexName())){
                    String paramListName = String.join("And", indexInfo.getColumnNames().stream().map( columnName-> StringUtil.initCap(columnName,true,columnPrefixes)).collect(Collectors.toList()));
                    selectByIndex.append("   <select id=\"selectBy"+paramListName+"\" resultMap=\"BaseResultMap\">\n" +
                            "        select\n" +
                            "        <include refid=\"Base_Column_List\"/>\n" +
                            "        from " + tableName + "\n" +
                            "        where ");
                    String condition = "";
                    List<ColumnInfo> v = indexInfo.getColumnInfos();
                    if (v.size() > 1) {
                        for (ColumnInfo columnInfo : v) {
                            condition += columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "} and";
                        }
                        condition = condition.substring(0, condition.length() - 4);
                        selectByIndex .append( condition + "\n");
                    } else {
                        ColumnInfo columnInfo = v.get(0);

                        selectByIndex .append( columnInfo.getColumnName() + " = #{" + StringUtil.initCap(columnInfo.getColumnName(), false, columnPrefixes) + "}\n");
                    }
                    selectByIndex .append("    </select>\n");

                }
            });
        }


        String content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
                "<!DOCTYPE mapper PUBLIC \"-//mybatis.org//DTD Mapper 3.0//EN\" \"http://mybatis.org/dtd/mybatis-3-mapper.dtd\">\n" +
                "<mapper namespace=\"" + mapperPackage + "." + beanName + "DAO\">\n" +
                "    <resultMap id=\"BaseResultMap\" type=\"" + beanPackage + "." + beanName + "\">\n" +
                resultMap +
                "    </resultMap>\n" +
                "\n" +
                "    <sql id=\"Base_Column_List\">\n" +
                "        " + columnList + "\n" +
                "    </sql>\n" +
                "\n" +
                filterList +
                "\n" +
                insert +
                "\n" +
                update +
                "\n" +
                delete +
                "\n" +
                selectByPrimaryKey +
                "\n" +
                selectByIndex.toString() +
                "\n" +
                query +
                "\n" +
                "</mapper>";
        FileUtil.write(content, "resources" + File.separator + mapperXmlPath, beanName + "DAOMapper.xml");
    }


}